home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65c+IDA-1.4.4.1 / src / macro.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-19  |  6.9 KB  |  318 lines

  1. /*
  2.  * Copyright (c) 1983 Eric P. Allman
  3.  * Copyright (c) 1988 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted provided
  7.  * that: (1) source distributions retain this entire copyright notice and
  8.  * comment, and (2) distributions including binaries display the following
  9.  * acknowledgement:  ``This product includes software developed by the
  10.  * University of California, Berkeley and its contributors'' in the
  11.  * documentation or other materials provided with the distribution and in
  12.  * all advertising materials mentioning features or use of this software.
  13.  * Neither the name of the University nor the names of its contributors may
  14.  * be used to endorse or promote products derived from this software without
  15.  * specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  17.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  18.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20.  
  21. #ifndef lint
  22. static char sccsid[] = "@(#)macro.c    5.7 (Berkeley) 6/1/90";
  23. static char  rcsid[] = "@(#)$Id: macro.c,v 5.7.0.7 1991/05/20 02:40:07 paul Exp $";
  24. #endif /* not lint */
  25.  
  26. # include "sendmail.h"
  27.  
  28. #ifdef __STDC__
  29. static bool mustquote(const char *);
  30. #else /* !__STDC__ */
  31. static bool mustquote();
  32. #endif /* __STDC__ */
  33.  
  34. /*
  35. **  EXPAND -- macro expand a string using $x escapes.
  36. **
  37. **    Parameters:
  38. **        s -- the string to expand.
  39. **        buf -- the place to put the expansion.
  40. **        buflim -- the buffer limit, i.e., the address
  41. **            of the last usable position in buf.
  42. **        e -- envelope in which to work.
  43. **
  44. **    Returns:
  45. **        none.
  46. **
  47. **    Side Effects:
  48. **        none.
  49. */
  50.  
  51. void
  52. expand(s, buf, buflim, e)
  53.     const char *s;
  54.     register char *buf;
  55.     const char *buflim;
  56.     register ENVELOPE *e;
  57. {
  58.     register char *xp;
  59.     register char *q;
  60.     bool skipping;        /* set if conditionally skipping output */
  61.     bool recurse = FALSE;    /* set if recursion required */
  62.     bool quote, inquote, inescape;
  63.     int i;
  64.     char xbuf[BUFSIZ];
  65.  
  66.     if (tTd(35, 24))
  67.     {
  68.         printf("expand(");
  69.         xputs(s);
  70.         printf(")\n");
  71.     }
  72.  
  73.     skipping = FALSE;
  74.     if (s == NULL)
  75.         s = "";
  76.     for (xp = xbuf; *s != '\0'; s++)
  77.     {
  78.         char c;
  79.  
  80.         /*
  81.         **  Check for non-ordinary (special?) character.
  82.         **    'q' will be the interpolated quantity.
  83.         */
  84.  
  85.         q = NULL;
  86.         quote = FALSE;
  87.         c = *s;
  88.         switch (c)
  89.         {
  90.           case CONDIF:        /* see if var set */
  91.             c = *++s;
  92.             skipping = macvalue(c, e) == NULL;
  93.             continue;
  94.  
  95.           case CONDELSE:    /* change state of skipping */
  96.             skipping = !skipping;
  97.             continue;
  98.  
  99.           case CONDFI:        /* stop skipping */
  100.             skipping = FALSE;
  101.             continue;
  102.  
  103.           case QUOTE822:
  104.             quote = TRUE;
  105.             /*FALLTHROUGH*/
  106.           case '\001':        /* macro interpolation */
  107.             c = *++s;
  108.             q = macvalue(c & 0177, e);
  109.             if (q == NULL)
  110.                 continue;
  111.             if (quote && !mustquote(q))
  112.                 quote = FALSE;
  113.             break;
  114.         }
  115.  
  116.         /*
  117.         **  Interpolate q or output one character
  118.         */
  119.  
  120.         if (skipping || xp >= &xbuf[(sizeof(xbuf)-1)])
  121.             continue;
  122.         inquote = FALSE;
  123.         inescape = FALSE;
  124.         if (q == NULL)
  125.             *xp++ = c;
  126.         else
  127.         {
  128.             /* copy to end of q or max space remaining in buf */
  129.             while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
  130.             {
  131.                 if (iscntrl(c) && !isspace(c))
  132.                     recurse = TRUE;
  133.                 if (quote)
  134.                 {
  135.                     if (!inquote)
  136.                     {
  137.                         *xp++ = '"';
  138.                         inquote = TRUE;
  139.                     }
  140.                     if (c == '"' && !inescape)
  141.                         *xp++ = '\\';
  142.                     if (c == '\\')
  143.                         inescape = !inescape;
  144.                     else
  145.                         inescape = FALSE;
  146.                 }
  147.                 *xp++ = c;
  148.             }
  149.             if (inescape && xp < &xbuf[sizeof xbuf - 1])
  150.                 *xp++ = '\\';
  151.             if (quote && xp < &xbuf[sizeof xbuf - 1])
  152.                 *xp++ = '"';
  153.         }
  154.     }
  155.     *xp = '\0';
  156.  
  157.     if (tTd(35, 24))
  158.     {
  159.         printf("expand ==> ");
  160.         xputs(xbuf);
  161.         printf("\n");
  162.     }
  163.  
  164.     /* recurse as appropriate */
  165.     if (recurse)
  166.     {
  167.         expand(xbuf, buf, buflim, e);
  168.         return;
  169.     }
  170.  
  171.     /* copy results out */
  172.     i = buflim - buf - 1;
  173.     if (i > xp - xbuf)
  174.         i = xp - xbuf;
  175.     bcopy(xbuf, buf, i);
  176.     buf[i] = '\0';
  177. }
  178. /*
  179. **  DEFINE -- define a macro.
  180. **
  181. **    this would be better done using a #define macro.
  182. **
  183. **    Parameters:
  184. **        n -- the macro name.
  185. **        v -- the macro value.
  186. **        e -- the envelope to store the definition in.
  187. **
  188. **    Returns:
  189. **        none.
  190. **
  191. **    Side Effects:
  192. **        e->e_macro[n] is defined.
  193. **
  194. **    Notes:
  195. **        There is one macro for each ASCII character,
  196. **        although they are not all used.  The currently
  197. **        defined macros are:
  198. **
  199. **        $a   date in ARPANET format (preferring the Date: line
  200. **             of the message)
  201. **        $b   the current date (as opposed to the date as found
  202. **             the message) in ARPANET format
  203. **        $c   hop count
  204. **        $d   (current) date in UNIX (ctime) format
  205. **        $e   the SMTP entry message+
  206. **        $f   raw from address
  207. **        $g   translated from address
  208. **        $h   to host
  209. **        $i   queue id
  210. **        $j   official SMTP hostname, used in messages+
  211. **        $k   our UUCP host name, if different from $w
  212. **        $l   UNIX-style from line+
  213. **        $m   to user before alias expansion
  214. **        $n   name of sendmail ("MAILER-DAEMON" on local
  215. **             net typically)+
  216. **        $o   delimiters ("operators") for address tokens+
  217. **        $p   my process id in decimal
  218. **        $q   the string that becomes an address -- this is
  219. **             normally used to combine $g & $x.
  220. **        $r   protocol used to talk to sender
  221. **        $s   sender's host name
  222. **        $t   the current time in seconds since 1/1/1970
  223. **        $u   to user
  224. **        $v   version number of sendmail
  225. **        $w   our host name (if it can be determined)
  226. **        $x   signature (full name) of from person
  227. **        $y   the tty id of our terminal
  228. **        $z   home directory of to person
  229. **
  230. **        Macros marked with + must be defined in the
  231. **        configuration file and are used internally, but
  232. **        are not set.
  233. **
  234. **        There are also some macros that can be used
  235. **        arbitrarily to make the configuration file
  236. **        cleaner.  In general all upper-case letters
  237. **        are available.
  238. */
  239.  
  240. void
  241. define(n, v, e)
  242.     char n;
  243.     char *v;
  244.     register ENVELOPE *e;
  245. {
  246.     if (tTd(35, 9))
  247.     {
  248.         printf("define(%c as ", n);
  249.         xputs(v);
  250.         printf(")\n");
  251.     }
  252.     e->e_macro[n & 0177] = v;
  253. }
  254. /*
  255. **  MACVALUE -- return uninterpreted value of a macro.
  256. **
  257. **    Parameters:
  258. **        n -- the name of the macro.
  259. **
  260. **    Returns:
  261. **        The value of n.
  262. **
  263. **    Side Effects:
  264. **        none.
  265. */
  266.  
  267. char *
  268. macvalue(n, e)
  269.     char n;
  270.     register ENVELOPE *e;
  271. {
  272.     n &= 0177;
  273.     while (e != NULL)
  274.     {
  275.         register char *p = e->e_macro[n];
  276.  
  277.         if (p == MACNULL)
  278.             /* shadowing null */
  279.             return (NULL);
  280.         if (p != NULL)
  281.             return (p);
  282.         e = e->e_parent;
  283.     }
  284.     return (NULL);
  285. }
  286. /*
  287. **  MUSTQUOTE -- Check if string contains special RFC-822 chars.
  288. **
  289. **    Parameters:
  290. **        s -- the string to be checked.
  291. **
  292. **    Returns:
  293. **        TRUE if string is in need to be quoted, FALSE otherwise.
  294. **
  295. **    Side Effects:
  296. **        none.
  297. **
  298. **    Does this string contain any characters that RFC 822 says
  299. **    must be quoted?
  300. **    This is not strictly correct, since we consider ' ' non-special.
  301. **    Otherwise we'd quote "My Name", which is just too ugly.
  302. */
  303. static bool
  304. mustquote(s)
  305.     register const char *s;
  306. {
  307.     register int c;
  308.  
  309.     while (c = *s++)
  310.     {
  311.         c &= 0177;
  312.         if (c <= 037 || c == 0177 ||         /* CTLs */
  313.             index(".()<>@,;:\\\"[]", c) != NULL)/* 822 specials */
  314.             return TRUE;
  315.     }
  316.     return FALSE;
  317. }
  318.